

<template>
    <div class="fund-calculator">
      <div class="flex-c">
        <a href="https://data.eastmoney.com/money/calc/FundCalcDTSY.html">
          天天基金定投计算器
        </a>
        <a href="https://danjuanfunds.com/calculator/zero?channel=2500000025&xueqiu_status_id=156481893&xueqiu_status_source=htl">
          雪球定投计算器
        </a>
      </div>
      <h1>基金定投收益计算器</h1>
      <form @submit.prevent="calculate">
        <div>
          <label for="startDate">开始日期:</label>
          <input type="date" id="startDate" v-model="startDate" required />
        </div>
        <div>
          <label for="endDate">结束日期:</label>
          <input type="date" id="endDate" v-model="endDate" required />
        </div>
        <div>
          <label for="frequency">投资频率:</label>
          <select id="frequency" v-model="frequency" required>
            <option value="daily">每日</option>
            <option value="weekly">每周</option>
            <option value="monthly">每月</option>
          </select>
        </div>
        <div v-if="frequency === 'weekly'">
          <label for="weekDay">选择星期几投:</label>
          <!-- JavaScript 的 getDay() 返回 0 表示星期日，1-6 分别为星期一至星期六 -->
          <select id="weekDay" v-model="weekDay">
            <option value="1">星期一</option>
            <option value="2">星期二</option>
            <option value="3">星期三</option>
            <option value="4">星期四</option>
            <option value="5">星期五</option>
            <option value="6">星期六</option>
            <option value="0">星期日</option>
          </select>
        </div>
        <div v-if="frequency === 'monthly'">
          <label for="monthDay">选择每月几号投:</label>
          <input type="number" id="monthDay" v-model.number="monthDay" min="1" max="31" />
        </div>
        <div>
          <label for="investAmount">每次定投金额:</label>
          <input type="number" id="investAmount" v-model.number="investAmount" required />
        </div>
        <button type="submit">计算</button>
      </form>
  
      <div id="results" v-if="resultCalculated">
        <h2>总体结果</h2>
        <p>定投次数: {{ investDatesCount }}</p>
        <p>总投入金额: {{ totalInvested.toFixed(2) }}</p>
        <p>累计购买份额: {{ totalUnits.toFixed(4) }}</p>
        <p>最终基金价值: {{ finalValue.toFixed(2) }}</p>
        <p>收益: {{ earnings.toFixed(2) }}</p>
        <p>持有天数: {{ holdingDays }}</p>
        
        <h2>每日明细</h2>
        <table border="1" cellspacing="0" cellpadding="5">
          <thead>
            <tr>
              <th>日期</th>
              <th>净值</th>
              <th>累计投入</th>
              <th>累计份额</th>
              <th>当前市值</th>
              <th>收益</th>
              <th>收益率 (%)</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in dailyBreakdown" :key="item.date">
              <td>{{ item.date }}</td>
              <td>{{ item.price.toFixed(4) }}</td>
              <td>{{ item.cumulativeInvest.toFixed(2) }}</td>
              <td>{{ item.cumulativeUnits.toFixed(4) }}</td>
              <td>{{ item.currentValue.toFixed(2) }}</td>
              <td>{{ item.earnings.toFixed(2) }}</td>
              <td>{{ item.yieldRate.toFixed(2) }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </template>
  
  <script>
  import data_json from '../../../assets/json/data.json'
  export default {
    name: 'FundCalculator',
    data() {
      return {
        startDate: "",
        endDate: "",
        frequency: "daily", // daily, weekly, monthly
        weekDay: "1",       // 默认星期一（仅 weekly 有效）
        monthDay: 1,        // 默认每月 1 号（仅 monthly 有效）
        investAmount: null,
        resultCalculated: false,
        totalInvested: 0,
        totalUnits: 0,
        finalValue: 0,
        earnings: 0,
        holdingDays: 0,
        investDatesCount: 0,
        dailyBreakdown: []
      }
    },
    methods: {
      calculate() {
        if (new Date(this.startDate) > new Date(this.endDate)) {
          alert("开始日期不能晚于结束日期！");
          return;
        }
            let data=data_json;
            // 根据文件格式，将 time 与 zdf 数组合并成记录数组
            const records = [];
            for (let i = 0; i < data.time.length; i++) {
              records.push({
                date: data.time[i],
                zdf: data.zdf[i]
              });
            }
            // 筛选出所选日期范围内的数据
            let filteredData = records.filter(item => {
              let itemDate = new Date(item.date);
              return itemDate >= new Date(this.startDate) && itemDate <= new Date(this.endDate);
            });
            if(filteredData.length === 0) {
              alert("所选日期范围内没有数据。");
              return;
            }
            // 按日期升序排序
            filteredData.sort((a, b) => new Date(a.date) - new Date(b.date));
            
            // 计算每日基金净值：第一天设为 1，之后根据涨跌幅累乘
            filteredData[0].price = 1;
            for (let i = 1; i < filteredData.length; i++) {
              let prevPrice = filteredData[i - 1].price;
              let change = parseFloat(filteredData[i].zdf);
              filteredData[i].price = prevPrice * (1 + change / 100);
            }
            
            // 筛选出符合定投条件的日期（用于总体统计）
            let investDates = filteredData.filter(item => {
              return this.isInvestDay(new Date(item.date));
            });
            if(investDates.length === 0) {
              alert("在所选日期范围和频率下，没有符合条件的投资日期。");
              return;
            }
            
            // 总体定投统计
            let totalInvested = 0;
            let totalUnits = 0;
            investDates.forEach(item => {
              let units = this.investAmount / item.price;
              totalUnits += units;
              totalInvested += this.investAmount;
            });
            let finalPrice = filteredData[filteredData.length - 1].price;
            let finalValue = totalUnits * finalPrice;
            let earnings = finalValue - totalInvested;
            let firstInvestDate = new Date(investDates[0].date);
            let holdingDays = Math.ceil((new Date(this.endDate) - firstInvestDate) / (1000 * 60 * 60 * 24));
            
            // 保存总体结果
            this.totalInvested = totalInvested;
            this.totalUnits = totalUnits;
            this.finalValue = finalValue;
            this.earnings = earnings;
            this.holdingDays = holdingDays;
            this.investDatesCount = investDates.length;
            
            // 生成每日明细：遍历所有日期，累计计算当日数据
            let dailyBreakdown = [];
            let cumulativeInvest = 0;
            let cumulativeUnits = 0;
            filteredData.forEach(item => {
              let currentDate = new Date(item.date);
              if (this.isInvestDay(currentDate)) {
                cumulativeInvest += this.investAmount;
                cumulativeUnits += this.investAmount / item.price;
              }
              let currentValue = cumulativeUnits * item.price;
              let earningsDay = currentValue - cumulativeInvest;
              let yieldRate = cumulativeInvest ? (currentValue / cumulativeInvest - 1) * 100 : 0;
              dailyBreakdown.push({
                date: item.date,
                price: item.price,
                cumulativeInvest,
                cumulativeUnits,
                currentValue,
                earnings: earningsDay,
                yieldRate
              });
            });
            this.dailyBreakdown = dailyBreakdown;
            this.resultCalculated = true;
      },
      // 判断某天是否为定投日
      isInvestDay(date) {
        if (this.frequency === "daily") {
          return true;
        } else if (this.frequency === "weekly") {
          return date.getDay() === parseInt(this.weekDay);
        } else if (this.frequency === "monthly") {
          return date.getDate() === Number(this.monthDay);
        }
        return false;
      }
    }
  }
  </script>
  
  <style scoped>
  .fund-calculator {
    font-family: Arial, sans-serif;
    margin: 20px;
  }
  .fund-calculator label {
    display: inline-block;
    width: 150px;
    margin-top: 10px;
  }
  .fund-calculator input,
  .fund-calculator select {
    margin-top: 10px;
  }
  .fund-calculator button {
    margin-top: 10px;
  }
  #results {
    margin-top: 20px;
  }
  table {
    margin-top: 10px;
    border-collapse: collapse;
  }
  th, td {
    padding: 5px;
    text-align: center;
  }
  </style>
  